#include "tskcfg.h"
#include "bsp.h"
#include "gui_base.h"
#include <string.h>

#define OLED_CMD  0	//写命令
#define OLED_DATA 1	//写数据

#define OLED_D0_Pin 								GPIO_PIN_8
#define OLED_D0_GPIO_Port 					GPIOD
#define OLED_D0(x)                	x?(OLED_D0_GPIO_Port->BSRR = OLED_D0_Pin):(OLED_D0_GPIO_Port->BRR = OLED_D0_Pin)

#define OLED_D1_Pin 								GPIO_PIN_12
#define OLED_D1_GPIO_Port 					GPIOA
#define OLED_D1(x)                	x?(OLED_D1_GPIO_Port->BSRR = OLED_D1_Pin):(OLED_D1_GPIO_Port->BRR = OLED_D1_Pin)

#define OLED_CS_Pin 								GPIO_PIN_9
#define OLED_CS_GPIO_Port 					GPIOD
#define OLED_CS(x)                	x?(OLED_CS_GPIO_Port->BSRR = OLED_CS_Pin):(OLED_CS_GPIO_Port->BRR = OLED_CS_Pin)

#define OLED_DC_Pin 								GPIO_PIN_10
#define OLED_DC_GPIO_Port 					GPIOA
#define OLED_DC(x)                	x?(OLED_DC_GPIO_Port->BSRR = OLED_DC_Pin):(OLED_DC_GPIO_Port->BRR = OLED_DC_Pin)

#define OLED_RES_Pin 								GPIO_PIN_11
#define OLED_RES_GPIO_Port 					GPIOA
#define OLED_RES(x)                	x?(OLED_RES_GPIO_Port->BSRR = OLED_RES_Pin):(OLED_RES_GPIO_Port->BRR = OLED_RES_Pin)

#define oled_scl_l()                OLED_D0(0)//D0
#define oled_scl_h()                OLED_D0(1)

#define oled_sda_l()                OLED_D1(0) //D1
#define oled_sda_h()                OLED_D1(1) 

#define oled_res_l()                OLED_RES(0)//RES
#define oled_res_h()                OLED_RES(1) 

#define oled_dc_l()                 OLED_DC(0)//DC
#define oled_dc_h()                 OLED_DC(1) 
 		     
#define oled_cs_l()                 OLED_CS(0)//CS
#define oled_cs_h()                 OLED_CS(1)

volatile static uint8_t framebuffer[128][8];


static void oled_io_init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  
  GPIO_InitStruct.Pin = OLED_DC_Pin|OLED_RES_Pin|OLED_D1_Pin;                        
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = OLED_D0_Pin|OLED_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}

static __inline void oled_send_byte(uint8_t dat, uint8_t cmd)
{
  uint8_t i;
  
  if(cmd)
  {
    oled_dc_h();
  }
	else
  {
    oled_dc_l();
  }
  
	oled_cs_l();
  
	for(i=0;i<8;i++)
	{
    oled_scl_l();
		
    if(dat&0x80)
    {
      oled_sda_h();
    }
		else
    {
      oled_sda_l();
    }
    
		oled_scl_h();
    
		dat<<=1;
	}
  
	oled_cs_h();

	oled_dc_h();
}

//反显函数
void OLed_ColorTurn(uint8_t i)
{
	if(i==0)
  {
    oled_send_byte(0xA6,OLED_CMD);//正常显示
  }
	if(i==1)
  {
    oled_send_byte(0xA7,OLED_CMD);//反色显示
  }
}

//屏幕旋转180度
void OLed_DisplayTurn(uint8_t i)
{
	if(i==0)
  {
    oled_send_byte(0xC8,OLED_CMD);//正常显示
    oled_send_byte(0xA1,OLED_CMD);
  }
	if(i==1)
  {
    oled_send_byte(0xC0,OLED_CMD);//反转显示
    oled_send_byte(0xA0,OLED_CMD);
  }
}

//开启OLED显示 
void OLed_DisPlay_On(void)
{
	oled_send_byte(0x8D,OLED_CMD);//电荷泵使能
	oled_send_byte(0x14,OLED_CMD);//开启电荷泵
	oled_send_byte(0xAF,OLED_CMD);//点亮屏幕
}

//关闭OLED显示 
void OLed_DisPlay_Off(void)
{
	oled_send_byte(0x8D,OLED_CMD);//电荷泵使能
	oled_send_byte(0x10,OLED_CMD);//关闭电荷泵
	oled_send_byte(0xAE,OLED_CMD);//关闭屏幕
}

//更新显存到OLED	
void Lcd_Refresh(void)
{
  uint8_t i,n;
  
	for(i=0;i<8;i++)
	{
    oled_send_byte(0xb0+i,OLED_CMD); //设置行起始地址
    oled_send_byte(0x00,OLED_CMD);   //设置低列起始地址
    oled_send_byte(0x10,OLED_CMD);   //设置高列起始地址
    
    for(n=0;n<128;n++)
    {
      oled_send_byte(framebuffer[n][i],OLED_DATA);
    }
  }
}

void Lcd_ClearScreen(void)
{
	memset((void *)framebuffer, 0, sizeof(framebuffer));
	Lcd_Refresh();
}

void Lcd_ClearFb(void)
{
	memset((void *)framebuffer, 0, sizeof(framebuffer));
}


void Lcd_DrawPixel(uint8_t x, uint8_t y, uint8_t color, uint8_t incolor)
{
  if((x>127) || (y > 63))
  {
    return;
  }
  
  if(incolor != 0x00)
	{
		if(color != 0x00)
		{
			framebuffer[x][y/8] |= (0x01<<(y%8));
		}
		else
		{
			framebuffer[x][y/8] &= ~(0x01<<(y%8));
		}
	}
	else
	{
		if(color != 0x00)
		{
			framebuffer[x][y/8] &= ~(0x01<<(y%8));
		}
		else
		{
			framebuffer[x][y/8] |= (0x01<<(y%8));
		}
	}
}

void Lcd_DrawVLine(uint16_t x, uint16_t y, uint16_t length)
{
	uint16_t i;
	
	for(i=0; i<length; i++)
	{
		framebuffer[x][(y+i)/8] |= (0x01<<((y+i)%8));
	}
}

void Lcd_DrawHLine(uint16_t x, uint16_t y, uint16_t length)
{
	uint16_t i;
	
	for(i=0; i<length; i++)
	{
		framebuffer[x+i][y/8] |= (0x01<<(y%8));
	}
}

void Lcd_DrawInvertHLine(uint16_t x, uint16_t y, uint16_t length)
{
	uint16_t i;
	
	for(i=0; i<length; i++)
	{
		framebuffer[x+i][y/8] ^= (0x01<<(y%8));
	}
}

//OLED的初始化
void Lcd_Init(void)
{
  oled_io_init();
  
	oled_res_l();
	vTaskDelay(200);
	oled_res_h();
	
	oled_send_byte(0xAE,OLED_CMD);//--turn off oled panel
	oled_send_byte(0x00,OLED_CMD);//---set low column address
	oled_send_byte(0x10,OLED_CMD);//---set high column address
	oled_send_byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	oled_send_byte(0x81,OLED_CMD);//--set contrast control register
	oled_send_byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
	oled_send_byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	oled_send_byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	oled_send_byte(0xA6,OLED_CMD);//--set normal display
	oled_send_byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	oled_send_byte(0x3f,OLED_CMD);//--1/64 duty
	oled_send_byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	oled_send_byte(0x00,OLED_CMD);//-not offset
	oled_send_byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	oled_send_byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	oled_send_byte(0xD9,OLED_CMD);//--set pre-charge period
	oled_send_byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	oled_send_byte(0xDA,OLED_CMD);//--set com pins hardware configuration
	oled_send_byte(0x12,OLED_CMD);
	oled_send_byte(0xDB,OLED_CMD);//--set vcomh
	oled_send_byte(0x40,OLED_CMD);//Set VCOM Deselect Level
	oled_send_byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	oled_send_byte(0x02,OLED_CMD);//
	oled_send_byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	oled_send_byte(0x14,OLED_CMD);//--set(0x10) disable
	oled_send_byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	oled_send_byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
  
	Lcd_ClearScreen();
  
	oled_send_byte(0xAF,OLED_CMD);
}

